/*
 * @Author: Wangjun
 * @Date: 2023-08-14 10:40:47
 * @LastEditTime: 2023-12-10 12:07:12
 * @LastEditors: wangjun haodreams@163.com
 * @Description:
 * @FilePath: \xr_node_calc\noderdb\op_ai_exp.go
 * hnxr
 */
package noderdb

import (
	"errors"
	"fmt"
	"strings"

	"gitee.com/haodreams/godriver/opdb"
	"gitee.com/haodreams/golib/logs"
	"gitee.com/haodreams/libs/expr"
	"gitee.com/haodreams/op_node/thirdparty"
	"gitee.com/hnxr_1/nodex"
)

func init() {
	nodex.Reister(new(EXP))
}

// 公式输入
type EXP struct {
	nodex.Node
	Exp       string //计算公式
	exp       *expr.Expression
	valid     bool //是否有效
	mapItem   map[string]*thirdparty.Item
	mapOpItem map[string]*opdb.Real
	Y         nodex.Double `remark:"输出Y,,out"`
	Tag       string       //标签
	Kind      string       //类别
}

func (m *EXP) GetModelID() int {
	return nodex.ModIn
}

func (m *EXP) GetName() string {
	return "AIEXP"
}

func (m *EXP) Init(mem *nodex.Memory) (err error) {
	extends := m.GetExtends()
	atag := extends["tag"]
	tag, _ := atag.(string)
	acategory := extends["category"]
	category, _ := acategory.(string)
	if tag != "" {
		m.Tag = tag
		m.Kind = category
		if m.Tag != "" {
			m.Exp = expr.ConvertIn(m.Tag, nil)
			m.exp, err = expr.Parse(m.Exp, m.Get)
			if err != nil {
				m.Bad = true
				err = fmt.Errorf("%s:%v", m.Exp, err)
				m.Err = err
				m.valid = false
				return
			}
			vars := m.exp.Vars()
			m.mapItem = make(map[string]*thirdparty.Item)
			m.mapOpItem = make(map[string]*opdb.Real)
			for _, key := range vars {
				if key == "" {
					continue
				}
				ss := strings.Split(key, ".")
				if len(ss) == 3 {
					logs.Info("OP POINT:", key)
					item := dataitem.GetOPValue(key, true)
					if item != nil {
						m.mapOpItem[key] = item
					}
				} else {
					item := dataitem.GetMemItem("", 0, key)
					logs.Info("VAR:", key)
					if item != nil {
						m.mapItem[key] = item
					}
				}
			}
			m.valid = true
		}
	}
	return
}

/**
 * @description: 节点信息
 * @return {*}
 */
func (m *EXP) RegData() []byte {
	return nodex.MakeRegData(m, "计算公式输入", m.GetName(), "")
}

func (m *EXP) Calc() (err error) {
	m.Bad = false
	if m.valid {
		if m.Exp == "" {
			m.Y.Value = 0
			return
		}
		m.Y.Value, err = m.exp.Eval()
		if err != nil {
			m.Bad = true
		}
		return
	} else {
		m.Bad = true
	}

	return
}

func (m *EXP) Get(name string) (float64, error) {
	ss := strings.Split(name, ".")
	if len(ss) == 3 {
		item := m.mapOpItem[name]
		if item != nil {
			return item.Value, nil
		}
		return 0, errors.New(name + "测点不存在")
	}
	item := m.mapItem[name]
	if item != nil {
		return item.V, nil
	}
	return 0, errors.New(name + "测点不存在")
}
